import 'dart:math';

import 'package:flutter/material.dart';

class GradientCircularProgressIndicator extends StatefulWidget {
  final double? width;
  final double? height;
  final double value; // 当前进度值
  final double strokeWidth; // 圆环宽度
  final Duration duration; // 动画持续时间
  final List<Color>? colors;

  const GradientCircularProgressIndicator(
      {Key? key,
      required this.value,
      this.width,
      this.height,
      this.strokeWidth = 8,
      this.duration = const Duration(milliseconds: 1000),
      this.colors})
      : super(key: key);

  @override
  _GradientCircularProgressIndicatorState createState() =>
      _GradientCircularProgressIndicatorState();
}

class _GradientCircularProgressIndicatorState
    extends State<GradientCircularProgressIndicator>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: widget.duration,
    );
    _animation = Tween<double>(begin: 0, end: widget.value).animate(_controller)
      ..addListener(() {
        setState(() {});
      });
    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width ?? 100,
      height: widget.height ?? 100,
      child: CustomPaint(
        painter: _GradientCirclePainter(
            animationValue: _animation.value,
            strokeWidth: widget.strokeWidth,
            colors: widget.colors),
      ),
    );
  }
}

class _GradientCirclePainter extends CustomPainter {
  final double animationValue;
  final double strokeWidth;
  final List<Color>? colors;

  _GradientCirclePainter(
      {required this.animationValue, required this.strokeWidth, this.colors});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..shader = LinearGradient(
        colors: colors ??
            [
              Colors.lightBlueAccent,
              Colors.lightBlueAccent.withAlpha(90),
            ],
        begin: Alignment(-1, -1),
        end: Alignment(1, 1),
      ).createShader(Rect.fromLTWH(0.0, 0.0, size.width, size.height));

    // final paintBg = Paint()
    //   ..shader = LinearGradient(
    //     colors: [
    //       Colors.grey,
    //     ],
    //     begin: Alignment(-1, -1),
    //     end: Alignment(1, 1),
    //   ).createShader(Rect.fromLTWH(0.0, 0.0, size.width, size.height));

    paint.style = PaintingStyle.stroke;
    paint.strokeCap = StrokeCap.round;
    paint.strokeWidth = strokeWidth;

    final center = size.center(Offset.zero);
    final radius = min(center.dx, center.dy);
    final rect = Rect.fromCircle(center: center, radius: radius);

    // canvas.drawArc(rect, -pi / 2, 2 * pi * animationValue, false, paintBg);
    canvas.drawArc(rect, -pi / 2, 2 * pi * animationValue, false, paint);
  }

  @override
  bool shouldRepaint(_GradientCirclePainter oldDelegate) {
    return oldDelegate.animationValue != animationValue ||
        oldDelegate.strokeWidth != strokeWidth;
  }
}
